package com.ljt.springtransactiondemo;

import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

@SpringBootApplication
@EnableAspectJAutoProxy(exposeProxy = true)
public class SpringTransactionDemoApplication {

    @Autowired
    private TransactionTemplate transactionTemplate;

    public static void main(String[] args) {
        // 测试传播行为
        // test1(args);

        // 测试编程式事务
        test2(args);
    }

    /**
     * 测试传播行为
     * @param args
     */
    public static void test1(String[] args) {
        var context = SpringApplication.run(SpringTransactionDemoApplication.class, args);
        SpringTransactionDemoApplication bean = context.getBean(SpringTransactionDemoApplication.class);
        bean.methodA();
    }

    /**
     * 测试编程式事务
     * @param args
     */
    public static void test2(String[] args) {
        var context = SpringApplication.run(SpringTransactionDemoApplication.class, args);
        SpringTransactionDemoApplication bean = context.getBean(SpringTransactionDemoApplication.class);
        bean.testTransactionTemplate();
    }


    @Autowired
    JdbcTemplate jdbcTemplate;

    @Transactional(propagation = Propagation.REQUIRED)
    void methodA() {
        jdbcTemplate.execute("insert into user(name, age) values('a', 18)");
        var o = (SpringTransactionDemoApplication) AopContext.currentProxy();

        // o.methodB();
        try { o.methodB(); }catch (Exception e){ e.printStackTrace();}

        /**
         * 测试nested
         */
        // throw new RuntimeException();
    }

    @Transactional(propagation = Propagation.REQUIRED)
    void methodB() {
        jdbcTemplate.update("insert into user(name, age) values(?, ?)", "b", 18);
        throw new RuntimeException();
    }

    // @Transactional(propagation = Propagation.REQUIRES_NEW)
    // void methodB() {
    //         jdbcTemplate.update("insert into user(name, age) values(?, ?)", "b", 18);
    //         throw new RuntimeException();
    // }

    // @Transactional(propagation = Propagation.NESTED)
    // void methodB() {
    //     jdbcTemplate.update("insert into user(name, age) values(?, ?)", "b", 18);
    //     throw new RuntimeException();
    // }

    // @Transactional(propagation = Propagation.NOT_SUPPORTED)
    // void methodB() {
    //     jdbcTemplate.update("insert into user(name, age) values(?, ?)", "b", 18);
    //     throw new RuntimeException();
    // }

    void testTransactionTemplate() {
        transactionTemplate.execute(status-> {
            jdbcTemplate.execute("insert into user(name, age) values('a', 18)");
            throw new RuntimeException();
            /**
             * 返回值自己随便返回，常见的就是返回userId，方便之后用呗。
             */
            // return null;
        });
    }

}
